package com.functest.util
/**
 * @author: DavydovMD
 * Date: 16.04.13
 * Time: 15:23
 */
class BitMaskState<T extends Enum> implements CodeBased {
    Class<T> clazz
    private List<T> bitsOn
    int code


    BitMaskState(Class clazz, int code) {
        this.clazz = clazz
        this.code = code
        this.bitsOn = calcBits(clazz, code)
    }


    BitMaskState(Class clazz, List<? extends CodeBased> bitsOn) {
        this.clazz = clazz;
        this.bitsOn = bitsOn;
        int code = 0
        bitsOn.each {
            code &= it.code
        }

    }

    static <T extends Enum> BitMaskState fromCode(Class<T> clazz, Integer code) {
        new BitMaskState<T>(clazz, code)
    }

    static <T extends Enum> BitMaskState fromBits(Class<T> clazz,  List<? extends CodeBased> bitsOn) {
        new BitMaskState<T>(clazz, bitsOn)
    }

    boolean has(T enum_value) {
        bitsOn.contains(enum_value)
    }

    List<T> getStates() {
        bitsOn.asImmutable()
    }



    protected static <T extends Enum> List calcBits(Class<T> clazz, int code) {
        def values = clazz.invokeMethod("values", [] as Object[]) as List<T>
        List<T> res = [];
        values.each {
            if (code & (it.getCode() as int)) {
                res << it
            }
        }
        res
    }

    @Override
    String toString() {
        "${this.bitsOn}"
    }

    int hashCode() {
        return this.code.hashCode()
    }

    boolean equals(Object o) {
        if (!(o instanceof BitMaskState)) return false
        BitMaskState bms = o as BitMaskState
        return bms.code == this.code
    }

    private setCode(int code) {
        this.code = code
        bitsOn = calcBits(clazz, code)
    }
}
